#include <iostream>
#include <Eigen/Dense>
#include<map>
#include<string>

using namespace std;
//用map储存创建的矩阵
map<string,Eigen::MatrixXd> stored_matrixs;


//用于得到正确的输入（排除输入字符串报错）
int getCorrectChoice(){
    int choice;

    while(true)
    {
        cout<<">>请输入："<<endl;
        cin>>choice;

        if(cin.fail()){
            cout<<"输入无效！请输入整数！"<<endl;
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(),'\n');//清除错误输入

        }
        else{
            cin.ignore(numeric_limits<streamsize>::max(),'\n');//清除缓冲区所有内容,清掉输入后产生的'\n'
            return choice;
        }


    }
}
//yes 或 no判断函数（判断是否储存运算结果）
bool getYOrN(){
    cout<<"\n"<<"是否储存该结果（y/n）？\n";
    string option;
    //清理上次输入残留的换行符
    cin.ignore(numeric_limits<streamsize>::max(),'\n');
    //判断是否存储结果
    while(true){
        getline(cin,option);//读取整行
        if(option=="n"){
            return false;
        }
        else if(option=="y"){
            return true;
        }
        else{
            cout<<"必须输入y或n！请重新输入："<<endl;
        }
}

}




//储存新矩阵
void saveNewMatrix(const Eigen::MatrixXd &operationResult){
    string matrix_name;
        cout<<"请输入新矩阵的名称（英文大写字母组合）："<<endl;
        cin>>matrix_name;
        
        auto it=stored_matrixs.find(matrix_name);
        while(it!=stored_matrixs.end()){
            cout<<"该矩阵名称已经存在！请尝试其他矩阵名："<<endl;
            cin>>matrix_name;
            it=stored_matrixs.find(matrix_name);
        }
        stored_matrixs[matrix_name]=operationResult;
        cout<<"【提示】创建成功"<<endl;
        cout<<"您创建的矩阵是："<<endl;
        cout<<matrix_name<<": "<<endl<<operationResult;

}


//创建和初始化矩阵
void CreateMatrix(){
    cout<<"【创建任意大小的矩阵】"<<endl;
    string matrix_name;
    cout<<"请输入矩阵的名称（英文大写字母组合）："<<endl;
    cin>>matrix_name;
    auto it=stored_matrixs.find(matrix_name);
    while(it!=stored_matrixs.end()){
        cout<<"该矩阵名称已经存在！请尝试其他矩阵名："<<endl;
        cin>>matrix_name;
        it=stored_matrixs.find(matrix_name);
    }

    int rows,cols;
    
    while(true){
        cout<<"请输入矩阵的行数和列数："<<endl;
        cin>>rows>>cols;
        if(rows<0||cols<0){
            cout<<"输入不能为负数！请重试！"<<endl;
        }
        else{
            break;
        }
    }
    
    Eigen::MatrixXd matrix_dynamic(rows,cols);
    cout<<"请输入"<<rows<<"x"<<cols<<"矩阵(元素间以空格分开)："<<endl;
    for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++){
            cin>>matrix_dynamic(i,j);
        }

    }
    cout<<endl;
    stored_matrixs[matrix_name]=matrix_dynamic;
    cout<<"【提示】创建成功"<<endl;
    cout<<"您创建的矩阵是："<<endl;
    cout<<matrix_name<<": "<<endl<<matrix_dynamic<<endl;
    cout<<"按任意键回到主菜单。。。"<<endl;


}
//创建方阵
void CreateSquareMatrix(){
    cout<<"【创建方阵】"<<endl;
    string matrix_name;
    cout<<"请输入矩阵的名称（英文大写字母组合）："<<endl;
    cin>>matrix_name;
    auto it=stored_matrixs.find(matrix_name);
    while(it!=stored_matrixs.end()){
        cout<<"该矩阵名称已经存在！请尝试其他矩阵名："<<endl;
        cin>>matrix_name;
        it=stored_matrixs.find(matrix_name);
    }
    
    int square;
    cout<<"请输入方阵的阶数(范围：1-4)："<<endl;

    
    do{
        square=getCorrectChoice();
        switch (square)
        {
            case 1:{
                Eigen::MatrixXd mat(1,1);
                cout<<"请输入这个1x1方阵"<<endl;
                cin>>mat(0,0);
                stored_matrixs[matrix_name]=mat;
                cout<<"【提示】创建成功"<<endl;
                cout<<"您创建的矩阵是："<<endl;
                cout<<matrix_name<<": "<<endl<<mat<<endl;
                cout<<"按任意键回到主菜单。。。"<<endl;

                break;
            }
            case 2:{
                Eigen::Matrix2d mat;
                cout<<"请输入这个2x2方阵(以空格分开):"<<endl;
                for(int i = 0; i < 2; i++) {
                    for(int j = 0; j < 2; j++) {
                        cin >> mat(i,j); 
                    }
                }
                stored_matrixs[matrix_name]=mat;
                cout<<"【提示】创建成功"<<endl;
                cout<<"您创建的矩阵是："<<endl;
                cout<<matrix_name<<": "<<endl<<mat<<endl;
                cout<<"按任意键回到主菜单。。。"<<endl;

                break;
            }
            case 3:{
                Eigen::Matrix3d mat;
                cout<<"请输入这个3x3方阵(以空格分开):"<<endl;
                for(int i = 0; i < 3; i++) {
                    for(int j = 0; j < 3; j++) {
                        cin >> mat(i,j); 
                    }
                }
                stored_matrixs[matrix_name]=mat;
                cout<<"【提示】创建成功"<<endl;
                cout<<"您创建的矩阵是："<<endl;
                cout<<matrix_name<<": "<<endl<<mat<<endl;
                cout<<"按任意键回到主菜单。。。"<<endl;



                break;
            }
            case 4:{
                Eigen::Matrix4d mat;
                cout<<"请输入这个4x4方阵(以空格分开):"<<endl;
                for(int i = 0; i < 4; i++) {
                    for(int j = 0; j < 4; j++) {
                        cin >> mat(i,j); 
                    }
                }

                stored_matrixs[matrix_name]=mat;
                cout<<"【提示】创建成功"<<endl;
                cout<<"您创建的矩阵是："<<endl;
                cout<<matrix_name<<": "<<endl<<mat<<endl;
                cout<<"按任意键回到主菜单。。。"<<endl;

                break;
            }
            default:
                cout<<"该阶数范围无效，请重新输入阶数："<<endl;
                break;
        
        }
    }while(square!=1&&square!=2&&square!=3&&square!=4);

}

//创建单位阵
void CreateIdentityMatrix(){
    cout<<"【创建单位阵】"<<endl;
    string matrix_name;
    cout<<"请输入矩阵的名称（英文大写字母组合）："<<endl;
    cin>>matrix_name;
    auto it=stored_matrixs.find(matrix_name);
    while(it!=stored_matrixs.end()){
        cout<<"该矩阵名称已经存在！请尝试其他矩阵名："<<endl;
        cin>>matrix_name;
        it=stored_matrixs.find(matrix_name);
    }
    int square;
    cout<<"请输入阶数："<<endl;
    square=getCorrectChoice();
    Eigen:: MatrixXd identity_mat=Eigen::MatrixXd::Identity(square,square);
    stored_matrixs[matrix_name]=identity_mat;
    cout<<endl;
    cout<<"【提示】创建成功"<<endl;
    cout<<"您创建的矩阵是："<<endl;
    cout<<matrix_name<<": "<<endl<<identity_mat;


}

void CreateZoreMatrix(){
    cout<<"【创建零矩阵】"<<endl;
    string matrix_name;
    cout<<"请输入矩阵的名称（英文大写字母组合）："<<endl;
    cin>>matrix_name;
    auto it=stored_matrixs.find(matrix_name);
    while(it!=stored_matrixs.end()){
        cout<<"该矩阵名称已经存在！请尝试其他矩阵名："<<endl;
        cin>>matrix_name;
        it=stored_matrixs.find(matrix_name);
    }
    int rows,cols;
    while(true){
        cout<<"请输入矩阵的行数和列数："<<endl;
        cin>>rows>>cols;
        if(rows<0||cols<0){
            cout<<"输入不能为负数！请重试！"<<endl;
        }
        else{
            break;
        }
    }
    Eigen:: MatrixXd zore_mat=Eigen::MatrixXd::Zero(rows,cols);
    stored_matrixs[matrix_name]=zore_mat;
    cout<<endl;
    cout<<"【提示】创建成功"<<endl;
    cout<<"您创建的矩阵是："<<endl;
    cout<<matrix_name<<": "<<endl<<zore_mat;

}

void CreateOneMatrix(){
    cout<<"【创建全1阵】"<<endl;
    string matrix_name;
    cout<<"请输入矩阵的名称（英文大写字母组合）："<<endl;
    cin>>matrix_name;
    auto it=stored_matrixs.find(matrix_name);
    while(it!=stored_matrixs.end()){
        cout<<"该矩阵名称已经存在！请尝试其他矩阵名："<<endl;
        cin>>matrix_name;
        it=stored_matrixs.find(matrix_name);
    }
    int rows,cols;
    while(true){
        cout<<"请输入矩阵的行数和列数："<<endl;
        cin>>rows>>cols;
        if(rows<0||cols<0){
            cout<<"输入不能为负数！请重试！"<<endl;
        }
        else{
            break;
        }
    }
    Eigen:: MatrixXd ones_mat=Eigen::MatrixXd::Ones(rows,cols);
    stored_matrixs[matrix_name]=ones_mat;
    cout<<endl;
    cout<<"【提示】创建成功"<<endl;
    cout<<"您创建的矩阵是："<<endl;
    cout<<matrix_name<<": "<<endl<<ones_mat;


}

void CreateRandomMatrix(){
    cout<<"【创建随机阵】"<<endl;
    string matrix_name;
    cout<<"请输入矩阵的名称（英文大写字母组合）："<<endl;
    cin>>matrix_name;
    
    auto it=stored_matrixs.find(matrix_name);
    while(it!=stored_matrixs.end()){
        cout<<"该矩阵名称已经存在！请尝试其他矩阵名："<<endl;
        cin>>matrix_name;
        it=stored_matrixs.find(matrix_name);
    }
    
    int rows,cols;
    while(true){
        cout<<"请输入矩阵的行数和列数："<<endl;
        cin>>rows>>cols;
        if(rows<0||cols<0){
            cout<<"输入不能为负数！请重试！"<<endl;
        }
        else{
            break;
        }
    }
    Eigen:: MatrixXd random_mat=Eigen::MatrixXd::Random(rows,cols);
    stored_matrixs[matrix_name]=random_mat;
    cout<<endl;
    cout<<"【提示】创建成功"<<endl;
    cout<<"您创建的矩阵是："<<endl;
    cout<<matrix_name<<": "<<endl<<random_mat;

}

void CreateSpecialMatrixMenu(){
    int choice;
    cout<<"请选择要创建的特殊矩阵：\n1.创建方阵\n2.创建全0阵\n3.创建全1阵\n4.创建单位阵\n5.创建随机阵\n"<<endl;
    do{
        choice=getCorrectChoice();
        switch(choice){
            case 1:{
                CreateSquareMatrix();
                char option;
                cout<<"\n是否继续创建？(y/n)"<<endl;
                cin>>option;
                if(option=='n'){
                    cout<<"返回上级菜单。。。"<<endl;

                    return;
                }
                cout<<"继续选择："<<endl;
                break;
            }
            case 2:{
                CreateZoreMatrix();
                char option;
                cout<<"\n是否继续创建？(y/n)"<<endl;
                cin>>option;
                if(option=='n'){
                    cout<<"返回上级菜单。。。"<<endl;

                    return;
                }
                cout<<"继续选择："<<endl;
                break;

            }
            case 3:{
                CreateOneMatrix();
                char option;
                cout<<"\n是否继续创建？(y/n)"<<endl;
                cin>>option;
                if(option=='n'){
                    cout<<"返回上级菜单。。。"<<endl;

                    return;
                }
                cout<<"继续选择："<<endl;
                break;

            }
            case 4:{
                CreateIdentityMatrix();
                char option;
                cout<<"\n是否继续创建？(y/n)"<<endl;
                cin>>option;
                if(option=='n'){
                    cout<<"返回上级菜单。。。"<<endl;

                    return;
                }
                cout<<"继续选择："<<endl;

                break;
            }
            case 5:{
                CreateRandomMatrix();
                char option;
                cout<<"\n是否继续创建？(y/n)"<<endl;
                cin>>option;
                if(option=='n'){
                    cout<<"返回上级菜单。。。"<<endl;

                    return;
                }
                cout<<"继续选择："<<endl;
                break;
            }
            default:
                cout<<"选择无效，请重新输入："<<endl;
                break;

        }
    }while(true);


}
//查看所有矩阵
void DisplayCreatedMatrixs(){
    cout<<"【创建的所有矩阵】"<<endl;
    cout<<"————————————————————————"<<endl;
    if(stored_matrixs.empty()){
        cout<<"【提示】还没创建任何矩阵！"<<endl;
        return;
    }
    for(auto it=stored_matrixs.begin();it!=stored_matrixs.end();++it)
    {
        cout<<it->first<<": "<<endl<<it->second<<endl;
        cout<<"------"<<endl;
        cout<<endl;
    }
    cout<<"显示完毕！"<<endl;


}

//矩阵运算
void addMatrix(){
    DisplayCreatedMatrixs();
    cout<<"请选择要相加的两个矩阵："<<endl;
    string choice1,choice2;
//找不到矩阵就要一直重试
    while(true)
    {
        cin>>choice1>>choice2;
        if(stored_matrixs.find(choice1)==stored_matrixs.end()||stored_matrixs.find(choice2)==stored_matrixs.end())
        {
            cout<<"矩阵不存在，请重新输入两个矩阵的名称："<<endl;

        }
        else{
            break;
        }
    }    
    //检查相加的两个矩阵维数是否匹配
    if(stored_matrixs[choice1].rows()!=stored_matrixs[choice2].rows()||stored_matrixs[choice1].cols()!=stored_matrixs[choice2].cols())
    {
        cout<<"【错误】这两个矩阵的维数不匹配！无法直接相加！"<<endl;
        return;

    }
    Eigen::MatrixXd sum=stored_matrixs[choice1]+stored_matrixs[choice2];
    cout<<choice1<<"+"<<choice2<<"结果为：\n"<<sum<<endl;
    
    bool result=getYOrN();
    if(!result){

        return;
    }
    else{
        saveNewMatrix(sum);
        return;

    }
        
    
    
    


}

void subMatrix(){
    DisplayCreatedMatrixs();
    cout<<"请选择要相减的两个矩阵："<<endl;
    string choice1,choice2;
//找不到矩阵就要一直重试
    while(true)
    {
        cin>>choice1>>choice2;
        if(stored_matrixs.find(choice1)==stored_matrixs.end()||stored_matrixs.find(choice2)==stored_matrixs.end())
        {
            cout<<"矩阵不存在，请重新输入两个矩阵的名称："<<endl;

        }
        else{
            break;
        }
    }    
     //检查减的两个矩阵维数是否匹配
    if(stored_matrixs[choice1].rows()!=stored_matrixs[choice2].rows()||stored_matrixs[choice1].cols()!=stored_matrixs[choice2].cols())
    {
        cout<<"【错误】这两个矩阵的维数不匹配！无法直接相减！"<<endl;
        return;

    }
    Eigen::MatrixXd diff=stored_matrixs[choice1]-stored_matrixs[choice2];
    cout<<choice1<<"-"<<choice2<<"结果为：\n"<<diff<<endl;
    
    bool result=getYOrN();
    if(!result){

        return;
    }
    else {
        saveNewMatrix(diff);
        return;

    }
    



}

void scalarMulMatrix(){
    DisplayCreatedMatrixs();
    cout<<"请选择要进行数乘的矩阵："<<endl;
    string choice;
//找不到矩阵就要一直重试
    while(true)
    {
        cin>>choice;
        if(stored_matrixs.find(choice)==stored_matrixs.end())
        {
            cout<<"矩阵不存在，请重新输入矩阵的名称："<<endl;

        }
        else{
            break;
        }
    }
    double k;
    cout<<"请输入要数乘的标量："<<endl;    
    cin>>k;
    Eigen::MatrixXd scalar_mul=k*stored_matrixs[choice];
    cout<<k<<"*"<<choice<<"结果为\n"<<scalar_mul<<endl;
    
   bool result=getYOrN();
    if(!result){
        return;
    }
    else{
       saveNewMatrix(scalar_mul);
        return;
    }
    
}

void mulMatrix(){
    DisplayCreatedMatrixs();
    cout<<"请选择要相乘的两个矩阵："<<endl;
    string choice1,choice2;
//找不到矩阵就要一直重试
    while(true)
    {
        cin>>choice1>>choice2;
        if(stored_matrixs.find(choice1)==stored_matrixs.end()||stored_matrixs.find(choice2)==stored_matrixs.end())
        {
            cout<<"矩阵不存在，请重新输入两个矩阵的名称："<<endl;

        }
        else{
            break;
        }
    }    
     //检查相加的两个矩阵维数是否匹配
    if(stored_matrixs[choice1].cols()!=stored_matrixs[choice2].rows())
    {
        cout<<"【错误】这两个矩阵不满足相乘的要求！无法直接相乘！"<<endl;
        return;

    }
    Eigen::MatrixXd mul=stored_matrixs[choice1]*stored_matrixs[choice2];
    cout<<choice1<<"*"<<choice2<<"的"<<"结果为：\n"<<mul<<endl;
    
    bool result=getYOrN();
    if(!result){
        return;
    }
    else{
        saveNewMatrix(mul);
        return;

    }
       
}

void TransposeMatrix(){
    DisplayCreatedMatrixs();
    cout<<"请选择要进行转置的矩阵："<<endl;
    string choice;

    while(true)
    {
        cin>>choice;
        if(stored_matrixs.find(choice)==stored_matrixs.end())
        {
            cout<<"矩阵不存在，请重新输入矩阵的名称："<<endl;

        }
        else{
            break;
        }
    }
    Eigen::MatrixXd transpose=stored_matrixs[choice].transpose();
    cout<<choice<<"转置的结果为：\n"<<transpose<<endl;
    
    bool result=getYOrN();
    if(!result){
        return;
    }
    else{
        saveNewMatrix(transpose);
        return;
    }

}


void GetMatrixSize(){
    DisplayCreatedMatrixs();
    cout<<"请选择要获取尺寸的矩阵："<<endl;
    string choice;

    while(true)
    {
        cin>>choice;
        if(stored_matrixs.find(choice)==stored_matrixs.end())
        {
            cout<<"矩阵不存在，请重新输入矩阵的名称："<<endl;
        }
        else{
            break;
        }
    }
    cout<<"行数："<<stored_matrixs[choice].rows()<<" "<<"列数："<<stored_matrixs[choice].cols()<<endl;
    int size=stored_matrixs[choice].size();
    cout<<"该矩阵大小为："<<size;
    

}

void IsMatrixEmpty(){
    DisplayCreatedMatrixs();
    cout<<"请选择要判断是否为空的矩阵："<<endl;
    string choice;
//找不到矩阵就要一直重试
    while(true)
    {
        cin>>choice;
        if(stored_matrixs.find(choice)==stored_matrixs.end())
        {
            cout<<"矩阵不存在，请重新输入矩阵的名称："<<endl;

        }
        else{
            break;
        }
    }
    Eigen::MatrixXd &matrix=stored_matrixs[choice];
    bool isEmpty=(matrix.size()==0);
    if(isEmpty){
        cout<<"该矩阵为空！"<<endl;
    }
    else{
        cout<<"该矩阵不为空"<<endl<<"它有"<<matrix.size()<<"个元素"<<endl;
    }


}
